#include <stdio.h>
#include <stdlib.h>
#include "label.h"
#include "register.h"
#include "AAT.h"
#include "AATBuildTree.h"
#include <string.h>
#include "codegen.h"



AATstatement assignmentTest(){

	int offsetX = 0;
	Label mainBlock = "main";
	int mainBlockSize = 4;
	

	return SequentialStatement(
		Allocate(
			AATExpressionList(
				AATMemoryAllocation(
					mainBlock,
					ConstantIntExpression(mainBlockSize)
				),
				NULL
			)
		),
		SequentialStatement(
			AssignmentStatement(
				IntegerVariable( mainBlock, offsetX ),
				ConstantIntExpression(999)
			),
			CallPrintStatement(
				IntegerVariable( mainBlock, offsetX)
			)
		)

	);

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement plusConstantTest(){

	int offsetX = 0;
	Label mainBlock = "main";
	int mainBlockSize = 4;
	

	return SequentialStatement(
		Allocate(
			AATExpressionList(
				AATMemoryAllocation(
					mainBlock,
					ConstantIntExpression(mainBlockSize)
				),
				NULL
			)
		),
		SequentialStatement(
			AssignmentStatement(
				IntegerVariable( mainBlock, offsetX ),
				OperatorExpression(
					ConstantIntExpression(999),
					ConstantIntExpression(666),
					AAT_PLUS
				)
			),
			CallPrintStatement(
				IntegerVariable( mainBlock, offsetX)
			)
		)

	);
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement plusVariableTest(){

	int offsetX = 0;
	int offsetY = 4;
	Label mainBlock = "main";
	int mainBlockSize = 8;

	return SequentialStatement(
				Allocate(
					AATExpressionList(
						AATMemoryAllocation(
							mainBlock,
							ConstantIntExpression(mainBlockSize)
						),
						NULL
					)
				),
				SequentialStatement(
					AssignmentStatement(
						IntegerVariable(mainBlock,offsetX), 
						ConstantIntExpression(999)
					),
					SequentialStatement(
						AssignmentStatement(
							IntegerVariable(mainBlock,offsetY), 
							ConstantIntExpression(666)
						),
						SequentialStatement(
							AssignmentStatement(
								IntegerVariable(mainBlock,offsetX),
								OperatorExpression(
									IntegerVariable(mainBlock,offsetX),
									IntegerVariable(mainBlock,offsetY),
									AAT_PLUS
								)
				
							),
							CallPrintStatement(
								IntegerVariable(mainBlock,offsetX)
							)
						)
					)

				)

			);
}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement ifThenTest(){

	int offsetX = 0;
	Label mainBlock = "main";
	int mainBlockSize = 4;

	return SequentialStatement(
				Allocate(
					AATExpressionList(
						AATMemoryAllocation(
							mainBlock,
							ConstantIntExpression(mainBlockSize)
						),
						NULL
					)
				),
				SequentialStatement(
					AssignmentStatement(
						IntegerVariable(mainBlock,offsetX), 
						ConstantIntExpression(0)
					),
					SequentialStatement(
						IfStatement(
							OperatorExpression(
								ConstantIntExpression(0),
								ConstantIntExpression(0),
								AAT_EQ
							),
							AssignmentStatement(
								IntegerVariable(mainBlock,offsetX),
								ConstantIntExpression(999) 
							),
							EmptyStatement()
						),
						CallPrintStatement(
							IntegerVariable(mainBlock,offsetX)
						)
					)
				)

			);
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement ifthenElseTest(){

	int offsetX = 0;
	int offsetY = 4;
	Label mainBlock = "main";
	int mainBlockSize = 8;

	return SequentialStatement(
				Allocate(
					AATExpressionList(
						AATMemoryAllocation(
							mainBlock,
							ConstantIntExpression(mainBlockSize)
						),
						NULL
					)
				),
				SequentialStatement(
					AssignmentStatement(
						IntegerVariable(mainBlock,offsetX),
						ConstantIntExpression(999)
					),
					SequentialStatement(
						   IfStatement(
							OperatorExpression(
								IntegerVariable(mainBlock,offsetX),
								ConstantIntExpression(1000),
								AAT_GT
							),
							AssignmentStatement(
								IntegerVariable(mainBlock,offsetY),
								ConstantIntExpression(666)
							),
							AssignmentStatement(
								IntegerVariable(mainBlock,offsetY),
								ConstantIntExpression(111)
							)
						),
						CallPrintStatement( 
							IntegerVariable(mainBlock,offsetY)
						)
					)	
				)

			);
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement whileDoTest(){

	int offsetX = 0;
	Label mainBlock = "main";
	int mainBlockSize = 4;

	return SequentialStatement(
				Allocate(
					AATExpressionList(
						AATMemoryAllocation(
							mainBlock,
							ConstantIntExpression(mainBlockSize)
						),
						NULL
					)
				),
				SequentialStatement(
					AssignmentStatement(
						IntegerVariable(mainBlock,offsetX),
						ConstantIntExpression(0)
					),
					WhileDoStatement(
						OperatorExpression(
							IntegerVariable(mainBlock,offsetX),
							ConstantIntExpression(10),
							AAT_LT
						),
						SequentialStatement(
							CallPrintStatement( 
								IntegerVariable(mainBlock,offsetX)
							),
							AssignmentStatement(
								IntegerVariable(mainBlock,offsetX),
								OperatorExpression(
									IntegerVariable(mainBlock,offsetX),
									ConstantIntExpression(1),
									AAT_PLUS
								)
							)
						)
					)
	
				)

			);
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AATstatement findPrimes(){

	const int MAX=100;
	int offsetX=0;
	int offsetI=4;
	int offsetOccurs=8;
	Label mainBlock = "main";
	int mainBlockSize = 12;


	return SequentialStatement(
				Allocate(
					AATExpressionList(
						AATMemoryAllocation(
							mainBlock,
							ConstantIntExpression(mainBlockSize)
						),
						NULL
					)
				),
				SequentialStatement(

					//----- i:=2 ---- //
					AssignmentStatement(
						IntegerVariable(mainBlock,offsetI),
						ConstantIntExpression(2)
					),
					SequentialStatement(
						//---- while i<MAX ---- //
						WhileDoStatement(
							OperatorExpression(
								IntegerVariable(mainBlock,offsetI),
								ConstantIntExpression(MAX),
								AAT_LT
							),
							//---- do ---- //
							SequentialStatement(
								//---- if i = 2 ---- //
								IfStatement(
									OperatorExpression(
										IntegerVariable(mainBlock,offsetI),
										ConstantIntExpression(2),
										AAT_EQ
									),
									//---- then print(I) ---- //
									CallPrintStatement( 
										IntegerVariable(mainBlock,offsetI)
									),
									//---- else ---- //
									SequentialStatement(
										//---- x:=2 ----//
										AssignmentStatement(
											IntegerVariable(mainBlock,offsetX),
											ConstantIntExpression(2)
										),
										SequentialStatement(
											//---- occurs:=0 ----//
											AssignmentStatement(
												IntegerVariable(mainBlock,offsetOccurs),
												ConstantIntExpression(0)
											),
											SequentialStatement(
												//---- while ----//
												WhileDoStatement(
													//---- x <= i div 2 ----//
													OperatorExpression(
														IntegerVariable(mainBlock,offsetX),
														OperatorExpression(
															IntegerVariable(mainBlock,offsetI),
															ConstantIntExpression(2),
															AAT_DIVIDE
														),
														AAT_LEQ
													),
													SequentialStatement(
														//---- DO ---- //
														//---- if i mod x = 0 ---- //
														IfStatement(
															OperatorExpression(
																OperatorExpression(
																	IntegerVariable(mainBlock,offsetI),
																	IntegerVariable(mainBlock,offsetX),
																	AAT_MODULO
																),
																ConstantIntExpression(0),
																AAT_EQ
															),
															//---- then ---- //
															//---- occurs:= occurs + 1 //
															AssignmentStatement(
																IntegerVariable(mainBlock,offsetOccurs),
																OperatorExpression(
																	IntegerVariable(mainBlock,offsetOccurs),
																	ConstantIntExpression(1),
																	AAT_PLUS
																)
															),
															//---- else (there is no else block)---- // 
															EmptyStatement()
														),
														//---- x:=x+1 ----//
														AssignmentStatement(
															IntegerVariable(mainBlock,offsetX),
															OperatorExpression(
																IntegerVariable(mainBlock,offsetX),
																ConstantIntExpression(1),
																AAT_PLUS
															)
														)
													)
												),
												//---- if occurs = 0 then print(I) ----//
												IfStatement(
													OperatorExpression(
														IntegerVariable(mainBlock,offsetOccurs),
														ConstantIntExpression(0),
														AAT_EQ
													),
													CallPrintStatement( 
														IntegerVariable(mainBlock,offsetI)
													),
													EmptyStatement()
												)
											)
										)
									)
								),
								//---- i:=i+1 ----//
								AssignmentStatement(
									IntegerVariable(mainBlock,offsetI),
									OperatorExpression(
										IntegerVariable(mainBlock,offsetI),
										ConstantIntExpression(1),
										AAT_PLUS
									)
								)
							)
						),
						EmptyStatement()
					)

				)

			);

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AATstatement arrayTest(){

	int offsetArray = 0;
	int elementSize = 4;
	int arrayLeftIndex = 10;
	int arrayRightIndex = 20;
	int offsetI = 4*(arrayRightIndex-arrayLeftIndex+1);

	Label mainBlock = "main";
	int mainBlockSize = 4*(arrayRightIndex-arrayLeftIndex+1) + 4;

	return SequentialStatement(
				Allocate(
					AATExpressionList(
						AATMemoryAllocation(
							mainBlock,
							ConstantIntExpression(mainBlockSize)
						),
						NULL
					)
				),
				SequentialStatement(
					AssignmentStatement(
						IntegerVariable(mainBlock,offsetI),
						ConstantIntExpression(0)
					),
					SequentialStatement(
						WhileDoStatement(
							OperatorExpression(
								IntegerVariable(mainBlock,offsetI),
								ConstantIntExpression(10),
								AAT_LEQ
							),
							SequentialStatement(
								AssignmentStatement(
									ArrayVariable(
										mainBlock,
										offsetArray,
										ConstantIntExpression(arrayLeftIndex),
										OperatorExpression(
											IntegerVariable(mainBlock,offsetI),
											ConstantIntExpression(10),
											AAT_PLUS
										),
										elementSize
									),
									OperatorExpression(
										IntegerVariable(mainBlock,offsetI),
										IntegerVariable(mainBlock,offsetI),
										AAT_MULTIPLY
									)
								),
								AssignmentStatement(
									IntegerVariable(mainBlock,offsetI),
									OperatorExpression(
										IntegerVariable(mainBlock,offsetI),
										ConstantIntExpression(1),
										AAT_PLUS
									)
								)
							)

						),
						SequentialStatement(
							CallPrintStatement(
								//Avar[11]
								ArrayVariable(
									mainBlock,
									offsetArray,
									ConstantIntExpression(arrayLeftIndex),
									ConstantIntExpression(11),
									elementSize
								)
							),
							CallPrintStatement(
								//Avar[16]
								ArrayVariable(
									mainBlock,
									offsetArray,
									ConstantIntExpression(arrayLeftIndex),
									ConstantIntExpression(16),
									elementSize
								)
							)	
						)
					)

				)

			);

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AATstatement recordTest(){

	int offsetI = 0;
	int offsetP = 4;
	int internalOffsetPx = 0;
	int internalOffsetPy = 4;

	Label mainBlock = "main";
	int mainBlockSize = 4+8;


	return SequentialStatement(
				Allocate(
					AATExpressionList(
						AATMemoryAllocation(
							mainBlock,
							ConstantIntExpression(mainBlockSize)
						),
						NULL
					)
				),
				SequentialStatement(
					AssignmentStatement(
						RecordVariable(
							mainBlock,
							offsetP,
							internalOffsetPx
						),
						ConstantIntExpression(666)
					),
					SequentialStatement(
						AssignmentStatement(
							RecordVariable(
								mainBlock,
								offsetP,
								internalOffsetPy
							),
							ConstantIntExpression(999)
						),
						SequentialStatement(
							CallPrintStatement(
								RecordVariable(
									mainBlock,
									offsetP,
									internalOffsetPx
								)
							),
							CallPrintStatement(
								RecordVariable(
									mainBlock,
									offsetP,
									internalOffsetPy
								)
							)
						)
					)
				)
			);
}



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement simpleProcedureInvocation(){

	Label mainBlock = "main";
	Label proc1Block = "proc1";		Label proc1BlockEnd = "proc1_end";
	int proc1ArgumentsSize = 0;
	int mainBlockSize = 0;
	int proc1BlockSize = 0;

	return SequentialStatement(
				Allocate(
					AATExpressionList(
						MemoryAllocation(
							mainBlock,
							mainBlockSize
						),
						AATExpressionList(
							MemoryAllocation(
								proc1Block,
								proc1BlockSize
							),
							NULL
						)
					)
				),
				SequentialStatement(
					ProcedureDefinition(
						CallPrintStatement(
							ConstantIntExpression(666)
						),
						proc1ArgumentsSize,
						proc1Block,
						proc1BlockEnd
					),
					SequentialStatement(
						CallStatement(
							proc1Block,
							NULL
						),
						CallPrintStatement(
							ConstantIntExpression(999)
						)
					)
				)
				
			);

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement nestedProcedureInvocation(){

	Label mainBlock = "main";
	Label proc1Block = "proc1";		Label proc1BlockEnd = "proc1_end";
	Label proc2Block = "proc2";		Label proc2BlockEnd = "proc2_end";
	int proc1ArgumentsSize = 0;
	int proc2ArgumentsSize = 0;
	int mainBlockSize = 0;
	int proc1BlockSize = 0;
	int proc2BlockSize = 0;

	return SequentialStatement(
				Allocate(
					AATExpressionList(
						MemoryAllocation(
							mainBlock,
							mainBlockSize
						),
						AATExpressionList(
							MemoryAllocation(
								proc2Block,
								proc2BlockSize
							),
							AATExpressionList(
								MemoryAllocation(
									proc1Block,
									proc1BlockSize
								),
								NULL
							)
						)
					)
				),
				SequentialStatement(
					ProcedureDefinition(
						SequentialStatement(
							CallStatement(
								proc2Block,
								NULL
							),
							CallPrintStatement(
								ConstantIntExpression(666)
							)
						),
						proc1ArgumentsSize,
						proc1Block,
						proc1BlockEnd
					),
					SequentialStatement(
						ProcedureDefinition(
							CallPrintStatement(
								ConstantIntExpression(333)
							),
							proc2ArgumentsSize,
							proc2Block,
							proc2BlockEnd
						),
						SequentialStatement(
							CallStatement(
								proc1Block,
								NULL
							),
							CallPrintStatement(
								ConstantIntExpression(999)
							)
						)
					)
				)
				
			);

}



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement procedureWithArguments(){

	Label mainBlock = "main";
	Label subProcedureBlock = "subProcedure";		Label subProcedureBlockEnd = "subProcedure_end";
	int subProcedureBlockArgumentsSize = 8;	// two integer arguments are passed to procedure
	int mainBlockSize = 4;					// one integer argument in main block
	int subProcedureBlockSize = 12;			// three integer variables in procedure

	int subProcedure_OffsetX = 4;
	int subProcedure_OffsetY = 0;
	int subProcedure_OffsetDiff = 8;

	int main_OffsetZ=0;


	return SequentialStatement(
				Allocate(
					AATExpressionList(
						MemoryAllocation(
							mainBlock,
							mainBlockSize
						),
						AATExpressionList(
							MemoryAllocation(
								subProcedureBlock,
								subProcedureBlockSize
							),
							NULL
						)
					)
				),
				SequentialStatement(
					ProcedureDefinition(
						SequentialStatement(
							AssignmentStatement(
								IntegerVariable(subProcedureBlock,subProcedure_OffsetDiff),
								OperatorExpression(
									IntegerVariable(subProcedureBlock,subProcedure_OffsetX),
									IntegerVariable(subProcedureBlock,subProcedure_OffsetY),
									AAT_MINUS
								)
							),
							CallPrintStatement(
								IntegerVariable(subProcedureBlock,subProcedure_OffsetDiff)
							)
						),
						subProcedureBlockArgumentsSize,
						subProcedureBlock,
						subProcedureBlockEnd
					),
					SequentialStatement(
						AssignmentStatement(
							IntegerVariable(mainBlock,main_OffsetZ),
							ConstantIntExpression(666)
						),
						CallStatement(
							subProcedureBlock,
							AATExpressionList(
								IntegerVariable(mainBlock,main_OffsetZ),
								AATExpressionList(
									ConstantIntExpression(66),
									NULL
								)
							)
						)
					)

				)

			);
}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AATstatement procedureVarReferenceTest(){
	Label mainBlock = "main";
	Label refProcBlock = "refProc";		Label refProcBlockEnd = "refProc_end";
	int refProcBlockArgumentsSize = 0;	// argument is a reference Don't allocate memory.
	int mainBlockSize = 4;					// one integer variable in main block
	int refProcBlockSize = 0;

	int main_OffsetZ=0;

	return SequentialStatement(
				Allocate(
					AATExpressionList(
						MemoryAllocation(
							mainBlock,
							mainBlockSize
						),
						AATExpressionList(
							MemoryAllocation(
								refProcBlock,
								refProcBlockSize
							),
							NULL
						)
					)
				),
				SequentialStatement(
					ProcedureDefinition(
						AssignmentStatement(
							IntegerVariable(mainBlock, main_OffsetZ),
							ConstantIntExpression(2000)
						),
						refProcBlockArgumentsSize,
						refProcBlock,
						refProcBlockEnd
					),
					SequentialStatement(
						AssignmentStatement(
							IntegerVariable(mainBlock, main_OffsetZ),
							ConstantIntExpression(1000)
						),
						SequentialStatement(
							CallPrintStatement(
								IntegerVariable(mainBlock, main_OffsetZ)
							),
							SequentialStatement(
								CallStatement(
									refProcBlock,
									NULL
								),
								CallPrintStatement(
									IntegerVariable(mainBlock, main_OffsetZ)
								)
							)
						)
					)

				)
			);
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement tailRecursionTest(){

	Label mainBlock = "main";
	Label recursionBlock = "recursion";		Label recursionBlockEnd = "recursion_end";
	int recursionBlockArgumentsSize = 4;	
	int mainBlockSize = 0;					
	int recursionBlockSize = 4;

	int recursion_OffsetX = 0;


	return SequentialStatement(
				Allocate(
					AATExpressionList(
						MemoryAllocation(
							mainBlock,
							mainBlockSize
						),
						AATExpressionList(
							MemoryAllocation(
								recursionBlock,
								recursionBlockSize
							),
							NULL
						)
					)
				),
				SequentialStatement(
					ProcedureDefinition(
						SequentialStatement(
							IfStatement(
								OperatorExpression(
									IntegerVariable(recursionBlock,recursion_OffsetX),
									ConstantIntExpression(5),
									AAT_LT
								),
								CallStatement(
									recursionBlock,
									AATExpressionList(
										OperatorExpression(
											IntegerVariable(recursionBlock,recursion_OffsetX),
											ConstantIntExpression(1),
											AAT_PLUS
										),
										NULL
									)
								),
								EmptyStatement()
							),
							CallPrintStatement(
								IntegerVariable(recursionBlock,recursion_OffsetX)
							)
						),
						recursionBlockArgumentsSize,
						recursionBlock,
						recursionBlockEnd					
					),
					CallStatement(
						recursionBlock,
						AATExpressionList(
							ConstantIntExpression(0),
							NULL
						)
					)

				)

			);


}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

AATstatement quickSort(){

	Label mainBlock = "main";
	Label fillArrayBlock = "fillArray";		Label fillArrayBlockEnd = "fillArray_end";
	Label printArrayBlock = "printArray";	Label printArrayBlockEnd = "printArray_end";
	Label quickSortBlock = "quickSort";	Label quickSortBlockEnd = "quickSort_end";

	int fillArrayBlockArgumentsSize = 0;	
	int printArrayBlockArgumentsSize = 0;
	int quickSortBlockArgumentsSize = 8;		// integer variables "lo" and "hi". "A" which is arrType var. reference is not taking in account

	int arrayLeftIndex = 1;
	int arrayRightIndex = 20;
	int arrayElementSize = 4;	// array consist of integer values


	int mainBlockSize = (arrayRightIndex-arrayLeftIndex+1)*arrayElementSize;					
	int fillArrayBlockSize = 4;
	int printArrayBlockSize = 4;
	int quickSortBlockSize = 28;

	int main_OffsetArr=0;
	int fillArray_OffsetI=0;
	int printArray_OffsetI=0;



/*procedure quickSort(var A : arrType; lo, hi : integer);
var
	i,j,h,x,t : integer;
*/
	int quickSort_OffsetHi=0;
	int quickSort_OffsetLo=4;
	int quickSort_OffsetI=8;
	int quickSort_OffsetJ=12;
	int quickSort_OffsetH=16;
	int quickSort_OffsetX=20;
	int quickSort_OffsetT=24;


	return SequentialStatement(
				// ==== memory allocation for each block ====
				Allocate(
					AATExpressionList(
						MemoryAllocation(
							mainBlock,
							mainBlockSize
						),
						AATExpressionList(
							MemoryAllocation(
								fillArrayBlock,
								fillArrayBlockSize
							),
							AATExpressionList(
								MemoryAllocation(
									printArrayBlock,
									printArrayBlockSize
								),
								AATExpressionList(
								MemoryAllocation(
									quickSortBlock,
									quickSortBlockSize
								),
								NULL
							)
							)
						)
					)
				),
				SequentialStatement(
					// ==== procedure fillArray() ====
					ProcedureDefinition(
						// ==== body definition
						SequentialStatement(
							// ==== i:=1 ====
							AssignmentStatement(
								IntegerVariable(fillArrayBlock, fillArray_OffsetI),
								ConstantIntExpression(1)
							),
							SequentialStatement(
								// ==== while ====
								WhileDoStatement(
									// ==== i<=20 ====
									OperatorExpression(
										IntegerVariable(fillArrayBlock, fillArray_OffsetI),
										ConstantIntExpression( 20 ),
										AAT_LEQ
									),
									// ==== arr[i]:= (20 - i)mod 6 ====
									SequentialStatement(
										AssignmentStatement(
											// ==== a[i] ====
											ArrayVariable(
												mainBlock,
												main_OffsetArr,
												ConstantIntExpression(arrayLeftIndex),
												IntegerVariable(fillArrayBlock, fillArray_OffsetI),
												arrayElementSize
											),
											OperatorExpression(
												// ==== (20 - i)mod 6 ====
												OperatorExpression(
													ConstantIntExpression(20),
													IntegerVariable(fillArrayBlock, fillArray_OffsetI),
													AAT_MINUS
												),
												ConstantIntExpression(6),
												AAT_MODULO
											)
										),
										SequentialStatement(
											// ==== i:=i+1
											AssignmentStatement(
												IntegerVariable(fillArrayBlock, fillArray_OffsetI),
												OperatorExpression(
													IntegerVariable(fillArrayBlock, fillArray_OffsetI),
													ConstantIntExpression(1),
													AAT_PLUS
												)
											),
											EmptyStatement()
										)

									)
								),
								EmptyStatement()
							)
						),
						// ==== size of arguments pass to the procedure
						fillArrayBlockArgumentsSize,
						// ==== name of the procedure ====
						fillArrayBlock,
						// ==== name of the end of the procedure: could be [name of the procedure] + [_end]
						fillArrayBlockEnd
					),
					SequentialStatement(
						// ==== procedure printArray() ====
						ProcedureDefinition(
							// ==== body definition
							SequentialStatement(
								// ==== i:=1 ====
								AssignmentStatement(
									IntegerVariable(printArrayBlock, printArray_OffsetI),
									ConstantIntExpression(1)
								),
								SequentialStatement(
									// ==== while ====
									WhileDoStatement(
										// ==== i<=20 ====
										OperatorExpression(
											IntegerVariable(printArrayBlock, printArray_OffsetI),
											ConstantIntExpression(20),
											AAT_LEQ
										),
										// ==== write(arr[i]) ====
										SequentialStatement(
											CallPrintStatement(
												// ==== a[i] ====
												ArrayVariable(
													mainBlock,
													main_OffsetArr,
													ConstantIntExpression(arrayLeftIndex),
													IntegerVariable(printArrayBlock, printArray_OffsetI),
													arrayElementSize
												)										
											),
											// ==== i:=i+1
											AssignmentStatement(
												IntegerVariable(printArrayBlock, printArray_OffsetI),
												OperatorExpression(
													IntegerVariable(printArrayBlock, printArray_OffsetI),
													ConstantIntExpression(1),
													AAT_PLUS
												)
											)
										)
									),
									EmptyStatement()
								)
							),
							// ==== size of arguments pass to the procedure
							printArrayBlockArgumentsSize,
							// ==== name of the procedure ====
							printArrayBlock,
							// ==== name of the end of the procedure: could be [name of the procedure] + [_end]
							printArrayBlockEnd
						),
						SequentialStatement(


							// ==== procedure quickSort(var A : arrType; lo, hi : integer) ====
							ProcedureDefinition(
								// ==== body definition
								SequentialStatement(
									// ==== i:=lo ====
									AssignmentStatement(
										IntegerVariable(quickSortBlock, quickSort_OffsetI),
										IntegerVariable(quickSortBlock, quickSort_OffsetLo)
									),
									SequentialStatement(
										// ==== j:=hi ====
										AssignmentStatement(
											IntegerVariable(quickSortBlock, quickSort_OffsetJ),
											IntegerVariable(quickSortBlock, quickSort_OffsetHi)
										),
										SequentialStatement(
											// ==== x:=A[(lo+hi)div 2] ====
											AssignmentStatement(
												IntegerVariable(quickSortBlock, quickSort_OffsetX),
												// ==== A[ index ]
												ArrayVariable(
													mainBlock,
													main_OffsetArr,
													ConstantIntExpression(arrayLeftIndex),
													// index == (lo+hi)div 2
													OperatorExpression(
														// ==== lo+hi
														OperatorExpression(
															IntegerVariable(quickSortBlock, quickSort_OffsetLo),
															IntegerVariable(quickSortBlock, quickSort_OffsetHi),
															AAT_PLUS
														),
														ConstantIntExpression(2),
														AAT_DIVIDE
													),
													arrayElementSize
												)												
											),
											SequentialStatement(
												// ==== t:=1 ====
												AssignmentStatement(
													IntegerVariable(quickSortBlock, quickSort_OffsetT),
													ConstantIntExpression(1)
												),
												SequentialStatement(

													// ==== while ====
													WhileDoStatement(
														// ==== t=1 ====
														OperatorExpression(
															IntegerVariable(quickSortBlock, quickSort_OffsetT),
															ConstantIntExpression(1),
															AAT_EQ
														),
														// ==== do (main while body) ====
														SequentialStatement(

															// ==== while (first inner while body) ====
															WhileDoStatement(
																// ==== A[i]<x ====
																OperatorExpression(
																	// ==== A[i] ====
																	ArrayVariable(
																		mainBlock,
																		main_OffsetArr,
																		ConstantIntExpression(arrayLeftIndex),
																		IntegerVariable(quickSortBlock, quickSort_OffsetI),
																		arrayElementSize
																	),	
																	IntegerVariable(quickSortBlock, quickSort_OffsetX),
																	AAT_LT
																),
																// ==== do ====
																SequentialStatement(
																	// ==== i:=i+1 ====
																	AssignmentStatement(
																		IntegerVariable(quickSortBlock, quickSort_OffsetI),
																		OperatorExpression(
																			IntegerVariable(quickSortBlock, quickSort_OffsetI),
																			ConstantIntExpression(1),
																			AAT_PLUS
																		)
																	),
																	EmptyStatement()
																)
															),
															SequentialStatement(
																// ==== while (second inner while body) ====
																WhileDoStatement(
																	// ==== A[j]>x ====
																	OperatorExpression(
																		// ==== A[j] ====
																		ArrayVariable(
																			mainBlock,
																			main_OffsetArr,
																			ConstantIntExpression(arrayLeftIndex),
																			IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																			arrayElementSize
																		),	
																		IntegerVariable(quickSortBlock, quickSort_OffsetX),
																		AAT_GT
																	),
																	// ==== do ====
																	SequentialStatement(
																		// ==== j:=j-1 ====
																		AssignmentStatement(
																			IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																			OperatorExpression(
																				IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																				ConstantIntExpression(1),
																				AAT_MINUS
																			)
																		),
																		EmptyStatement()
																	)
																),	
																SequentialStatement(
																	// ==== if i<=j ====
																	IfStatement(
																		OperatorExpression(
																			IntegerVariable(quickSortBlock, quickSort_OffsetI),
																			IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																			AAT_LEQ
																		),
																		// ==== then ====
																		SequentialStatement(
																			// h:=A[i]
																			AssignmentStatement(
																				IntegerVariable(quickSortBlock, quickSort_OffsetH),
																				ArrayVariable(
																					mainBlock,
																					main_OffsetArr,
																					ConstantIntExpression(arrayLeftIndex),
																					IntegerVariable(quickSortBlock, quickSort_OffsetI),
																					arrayElementSize
																				)																		
																			),
																			SequentialStatement(
																				// A[i]:=A[j]
																				AssignmentStatement(
																					ArrayVariable(
																						mainBlock,
																						main_OffsetArr,
																						ConstantIntExpression(arrayLeftIndex),
																						IntegerVariable(quickSortBlock, quickSort_OffsetI),
																						arrayElementSize
																					),
																					ArrayVariable(
																						mainBlock,
																						main_OffsetArr,
																						ConstantIntExpression(arrayLeftIndex),
																						IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																						arrayElementSize
																					)																		
																				),	
																				SequentialStatement(
																					// A[j]:=h
																					AssignmentStatement(
																						ArrayVariable(
																							mainBlock,
																							main_OffsetArr,
																							ConstantIntExpression(arrayLeftIndex),
																							IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																							arrayElementSize
																						),
																						IntegerVariable(quickSortBlock, quickSort_OffsetH)																		
																					),	
																					SequentialStatement(
																						// ==== i:=i+1
																						AssignmentStatement(
																							IntegerVariable(quickSortBlock, quickSort_OffsetI),
																							OperatorExpression(
																								IntegerVariable(quickSortBlock, quickSort_OffsetI),
																								ConstantIntExpression(1),
																								AAT_PLUS
																							)
																						),
																						SequentialStatement(
																							// ==== j:=j-1
																							AssignmentStatement(
																								IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																								OperatorExpression(
																									IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																									ConstantIntExpression(1),
																									AAT_MINUS
																								)
																							),
																							EmptyStatement()
																						)
																					)
																				)
																			)

																		),
																		EmptyStatement()
																	), // ==== end if i<=j statement
																	
																	SequentialStatement(
																		// ==== if i>j ====
																		IfStatement(
																			OperatorExpression(
																				IntegerVariable(quickSortBlock, quickSort_OffsetI),
																				IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																				AAT_GT
																			),
																			// ==== then ====
																			AssignmentStatement(
																				IntegerVariable(quickSortBlock, quickSort_OffsetT),
																				ConstantIntExpression(0) 
																			),
																			// ==== else body is empty ====
																			EmptyStatement()
																		),
																		EmptyStatement()
																	)

																)

															)
														)
													),	// ==== end main while body ====
													SequentialStatement(
														// ==== if lo<j  ====
														IfStatement(
															OperatorExpression(
																IntegerVariable(quickSortBlock, quickSort_OffsetLo),
																IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																AAT_LT
															),
															// ==== then quickSort(A, lo, j) ====
															CallStatement(
																quickSortBlock,
																AATExpressionList(
																	IntegerVariable(quickSortBlock, quickSort_OffsetLo),
																	AATExpressionList(
																		IntegerVariable(quickSortBlock, quickSort_OffsetJ),
																		NULL
																	)		
																)										
															),
															// ==== else block is empty
															EmptyStatement()
														),
														SequentialStatement(
															// ==== 	if i<hi  ====
															IfStatement(
																OperatorExpression(
																	IntegerVariable(quickSortBlock, quickSort_OffsetI),
																	IntegerVariable(quickSortBlock, quickSort_OffsetHi),
																	AAT_LT
																),
																// ==== then quickSort(A,i, hi)====
																CallStatement(
																	quickSortBlock,
																	AATExpressionList(
																		IntegerVariable(quickSortBlock, quickSort_OffsetI),
																		AATExpressionList(
																			IntegerVariable(quickSortBlock, quickSort_OffsetHi),
																			NULL
																		)		
																	)										
																),
																// ==== else block is empty
																EmptyStatement()
															),
															EmptyStatement()

														)

													)

												)

											)
		
										)
									)
								),
								// ==== size of arguments pass to the procedure
								quickSortBlockArgumentsSize,
								// ==== name of the procedure ====
								quickSortBlock,
								// ==== name of the end of the procedure: could be [name of the procedure] + [_end]
								quickSortBlockEnd
							),

							SequentialStatement(
								CallStatement(
									fillArrayBlock,
									NULL
								),
								SequentialStatement(
									CallStatement(
										printArrayBlock,
										NULL
									),
									SequentialStatement(
										CallPrintLineStatement(),
										SequentialStatement(
											CallStatement(
												quickSortBlock,
												AATExpressionList(
													ConstantIntExpression( arrayLeftIndex ),
													AATExpressionList(
														ConstantIntExpression( arrayRightIndex ),
														NULL
													)		
												)										
											),
											CallStatement(
												printArrayBlock,
												NULL
											)
										)

									)

								)

							)



						)

					)
				)
			);

}

